<!DOCTYPE html>
<html lang="zh-CN">
	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<title>SwiftJSON</title>

		<!--begin code mirror -->
		<!-- 两个核心文件 -->
		<link rel="stylesheet" href="codemirror/lib/codemirror.css" />
		<script src="codemirror/lib/codemirror.js"></script>
		<!-- Swift语法高亮 -->
		<script src="codemirror/mode/swift/swift.js"></script>
		<!-- 主题 -->
		<link rel="stylesheet" href="codemirror/theme/dracula.css" />
		<link rel="stylesheet" href="codemirror/theme/solarized.css" />
		<!--括号匹配-->
		<script src="codemirror/addon/edit/matchbrackets.js"></script>
		<script src="codemirror/addon/edit/matchtags.js"></script>
		<!--end Code Mirror -->

		<script src="js/jquery-1.12.4.min.js"></script>

		<script type="text/javascript">
			var prSelf = "self.";
			
			$(function() {
				// 1.清空
				$('#clearBtn').click(function() {
					inEditor.setValue("");
				});

				// 2.复制
				$('#copyBtn').click(function() {
					let s = outEditor.getValue();
					if (s.length < 6) {
						return;
					}
					outEditor.focus();
					outEditor.execCommand("selectAll");
					document.execCommand("copy");
					// window.document.execCommand("Copy");
				});

				// 3.SelfBtn
				$('#selfBtn').click(function() {
					var temp = $("#selfBtn").val();
					if (temp == "不要Self") {
						$("#selfBtn").val("加上Self");
						prSelf = "";
					} else {
						$("#selfBtn").val("不要Self");
						prSelf = "self.";
					}
				});

				// 4.转换
				$('#foramteBtn').click(function() {
					outEditor.setValue("");

					// 1.获取全部内容
					var allString = inEditor.getValue();

					if (allString.length <= 0) {
						alert("请输入内容")
						return;
					}

					// 2.分割字符串，每一行，--> 去掉前后空格 --> 去掉注释
					// https://www.jb51.net/article/109522.htm
					var allArray = allString.split("\n").map(function(item) {
						return $.trim(item);
					}).filter(function(item) {
						return item.indexOf("/") != 0;
					});
						
					// 3.解析数据
					for (var line of allArray) {
						if (line.length <= 0) {
							continue;
						}

						if (line.length < 6) { 
							var temp = "// 解析失败行: " + line;
							outEditor.setValue(outEditor.getValue() + "\n" + temp);
							continue;
						}

						if (line.search(":") == -1) {
							formateLineBB(line);
							continue;
						}
						formateLineAA(line);
					}

					outEditor.setValue($.trim(outEditor.getValue()));
					formateLineCC()
				});
			});

			// 将输入框的内容，格式化一下，去掉前后空格和无意义的换行
			function formateLineCC() {
				// 1.获取全部内容
				var allString = inEditor.getValue();

				// 2.分割字符串，每一行，--> 去掉前后空格 --> 去掉注释
				// https://www.jb51.net/article/109522.htm
				allString = allString.split("\n").map(function(item) {
					return $.trim(item);
				}).filter(function(item) {
					return item.length >= 1;
				}).join("\n");

				inEditor.setValue(allString);
			}

			// 含有:的情况
			function formateLineAA(line) {
				if (line.indexOf(":") == -1) {
					var temp = "// 解析失败行: " + line;
					outEditor.setValue(outEditor.getValue() + "\n" + temp);
					return;
				}

				// let name: String = "123"
				// let name: String?
				// let name: String? = nil
				// let name: [Int] = []
				// let name: [String: Int] = [:]
				// let name: Class?
				try {
					// 1.以:分割分组
					var arraAA = line.split(":");
					var letVar = arraAA[0].split(" ")[0];
					if (letVar != "var" && letVar != "let") {
						var temp = "// 解析失败行: " + line;
						outEditor.setValue(outEditor.getValue() + "\n" + temp);
						return;
					}
					// 1.1 拿到属性名
					var pName = arraAA[0].split(" ")[1];
					// 1.2 判断属性类型
					var pType = "";
					var tName = $.trim(arraAA[1]);

					if (tName.indexOf("String") == 0) {
						pType = ".stringValue";
					} else if (tName.indexOf("Int") == 0) {
						pType = ".intValue";
					} else if (tName.indexOf("Bool") == 0) {
						pType = ".boolValue";
					} else if (tName.indexOf("Double") == 0) {
						pType = ".doubleValue";
					} else if (tName.indexOf("Float") == 0) {
						pType = ".floatValue";
					} else if (tName.indexOf("[") != -1 && tName.indexOf("]") == -1) {
						pType = " // 😝不知道咋解析，记得手动处理我😝";
					} else if (tName.indexOf("[") == 0) {
						pType = ".arrayValue // 😝需要检查我";
					} else {
						pType = " // 😝不知道咋解析，记得手动处理我😝";
					}

					var temp = prSelf + pName + " = " + "json[\"" + pName + "\"]" + pType;
					outEditor.setValue(outEditor.getValue() + "\n" + temp);

				} catch(err) {
					console.log("😝BB捕获到异常: ", err.message);
					var temp = "// 解析失败行: " + line;
					outEditor.setValue(outEditor.getValue() + "\n" + temp);
				}
			}

			// 没有:的情况，比如`let name = ""`
			function formateLineBB(line) {
				if (line.indexOf("=") == -1) {
					var temp = "// 解析失败行: " + line;
					outEditor.setValue(outEditor.getValue() + "\n" + temp);
					return;
				}

				// let name = ""
				// let name = "HouWan"
				// let age = 0
				// let age = 12.0
				// let age = 1
				try {
					// 1.以=分割分组
					var arraAA = line.split("=");
					var letVar = arraAA[0].split(" ")[0];
					if (letVar != "var" && letVar != "let") {
						var temp = "// 解析失败行: " + line;
						outEditor.setValue(outEditor.getValue() + "\n" + temp);
						return;
					}
					// 1.1 拿到属性名
					var pName = arraAA[0].split(" ")[1];
					// 1.2 判断属性类型
					var pType = "";
					var tName = $.trim(arraAA[1]);
					if (tName.indexOf("\"") != -1) {
						pType = ".stringValue";
					} else if (tName.indexOf("true") != -1 || tName.indexOf("false") != -1) {
						pType = ".boolValue";
					} else if (tName.indexOf(".") != -1) {
						pType = ".doubleValue";
					} else {
						pType = ".intValue";
					}
					var temp = prSelf + pName + " = " + "json[\"" + pName + "\"]" + pType;
					outEditor.setValue(outEditor.getValue() + "\n" + temp);

				} catch(err) {
					console.log("😝BB捕获到异常: ", err.message);
					var temp = "// 解析失败: " + line;
					outEditor.setValue(outEditor.getValue() + "\n" + temp);
				}
			}
		</script>

		<style type="text/css">
			input {
				height: 25px;
				width: 80px;
			}
			.spView {
				height: 8px;
			}
			.tempCode {
				border: 1px solid blueviolet;
				width: 770px;
				font-size: 14px;
				color: #1b315e;
				height: 300px;
				padding: 5px 15px 5px 15px;
			}
			.tempCodeSwift {
				border: 1px solid blueviolet;
				width: 770px;
				font-size: 14px;
				color: #1b315e;
				height: 480px;
				padding: 5px 15px 5px 15px;
			}
		</style>

	</head>
	<body>
		<h1>快捷处理SwiftJSON</h1>
		<p>在下面输入或者粘贴属性：</p>
		<textarea id="inText" name="inCode"></textarea>

		<div class="spView"></div>
		<input type="button" value="转换" id="foramteBtn">
		<input type="button" value="清空" id="clearBtn">
		<input type="button" value="复制结果" id="copyBtn">
		<input type="button" value="不要Self" id="selfBtn">
		<div class="spView"></div>

		<!-- readonly="readonly" -->
		<textarea id="outText" name="outCode">// 等待结果...</textarea>
		<br>
		<p>1. 对于解析到的`12.00`的浮点型都是转为`doubleValue`</p>
		<p>2. 除非明确浮点型是`Float`，才能解析为`floatValue`</p>
		<p>3. 下面的写法全部能解析，无论你是否加了空格，也不管是`let`还是`var` </p>
<div class="tempCode">
let name: String = "123"<br>
let name: String?<br>
let name: String? = nil<br>
let name: [Int] = []<br>
let name: [String: Int] = [:]<br>
let name: Class?<br>
let name = ""<br>
let name = "HouWan"<br>
let age = 0<br>
let age = 12.0<br>
let age = 1<br>
var have = true<br>
var hit = false<br>
var xx: Bool?<br>
var xx: Bool = true<br>
</div>

<p>SwiftyJSON模型写法代码示例</p>
<div class="tempCodeSwift">
// ============ 方法一，提前赋值，可以后再JSON赋值 ============<br>
class MeModel {<br>
&nbsp;&nbsp;&nbsp;&nbsp;/// 会员id<br>
&nbsp;&nbsp;&nbsp;&nbsp;var memberId: String = ""<br>
&nbsp;&nbsp;&nbsp;&nbsp;/// 性别 0男 1女<br>
&nbsp;&nbsp;&nbsp;&nbsp;var sex: Int = 0<br>

<br>
/// 后初始化方法<br>
func setupWith(_ json: SwiftyJSON.JSON) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;if json.isEmpty {<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;memberId = json["memberId"].stringValue<br>
&nbsp;&nbsp;&nbsp;&nbsp;sex = json["sex"].intValue<br>
}<br>

// ============ 方法二，使用Let属性 ============<br>
struct CardModel {<br>
&nbsp;&nbsp;&nbsp;&nbsp;/// 门店名<br>
&nbsp;&nbsp;&nbsp;&nbsp;let storeName: String<br>
&nbsp;&nbsp;&nbsp;&nbsp;// 初始化模型<br>
&nbsp;&nbsp;&nbsp;&nbsp;init(_ json: SwiftyJSON.JSON) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 不想判断 json.isEmpty 的话，最好使用 ?? 进行数据容错<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.storeName = json["storeName"].string ?? "健身房"<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}<br>
</div>


<script type="text/javascript">
	// 根据DOM元素的id构造出一个编辑器
	var inEditor = CodeMirror.fromTextArea(document.getElementById("inText"), {
		lineNumbers: true,     // 显示行数
		indentUnit: 4,         // 缩进单位为4
		styleActiveLine: true, // 当前行背景高亮
		matchBrackets: true,   // 括号匹配
		mode: "text/x-swift",  // 实现swift代码高亮
		theme: "solarized",      // 设置主题
	});
	inEditor.setSize('800px', '310px');

	var outEditor = CodeMirror.fromTextArea(document.getElementById("outText"), {
		lineNumbers: true,     // 显示行数
		indentUnit: 4,         // 缩进单位为4
		styleActiveLine: true, // 当前行背景高亮
		matchBrackets: true,   // 括号匹配
		mode: "text/x-swift",  // 实现swift代码高亮
		theme: "solarized",      // 设置主题
		// readOnly: true,        // 只读
	});
	outEditor.setSize('800px', '310px');

	// $(function() {
	// 	// 1.清空
	// 	$('#clearBtn').click(function() {
	// 		// inEditor.setValue("let name = ");
	// 		console.log(prSelf);
	// 	});
	// });
	
</script>

<style type="text/css">
	.textView {
		font-size: 30px;
		line-height: 110%;
		background-color: brown;
	}
</style>

	</body>
</html>